/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package recommender.dbi;

import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import recommender.objects.Context;
import recommender.objects.Entity;
import recommender.objects.Preference;
import recommender.objects.User;
import recommender.objects.Video;

/**
 *
 * @author Aya
 */
public class LTUBI extends UBI{

    private final EntityManager em;
    
    public LTUBI(){
        EntityManagerFactory factory = Persistence.createEntityManagerFactory("RecommenderPU");
        em = factory.createEntityManager();   
    }
    
    @Override
    public int createUser(String un, String pwd, String n, String country, Date dob) {
        Query q = em.createNativeQuery("INSERT INTO ub.user (username, password, name, country, dob) "
                + "VALUES (?1, ?2, ?3, ?4, ?5) RETURNING id");
        q.setParameter(1, un);
        q.setParameter(2, pwd);
        q.setParameter(3, n);
        q.setParameter(4, country);
        q.setParameter(5, dob);
        return (Integer) q.getResultList().get(0);
    }

    @Override
    public User loadUser(String un, String pwd) {
        Query q = em.createNativeQuery("SELECT * FROM ub.user WHERE username = ?1 and password = ?2", User.class);
        q.setParameter(1, un);
        q.setParameter(2, pwd);
        List<User> res = q.getResultList();
        if(res == null || res.isEmpty()){
            return null;
        }
        
        User u = res.get(0);
        u.setCurActiveContext(getCurActive(u.getId()));
        u.setExplicitInterests(getInterests(u.getId()));
        u.setExplicitDislikes(getDisinterests(u.getId()));
        u.setLikeList(getLikeVideos(u.getId()));
        u.setDislikeList(getDislikeVideos(u.getId()));
        u.setPreferences(getPreferences(u.getId()));
        return u;
    }
    
    @Override
    public User loadUser(int uid) {
        Query q = em.createNativeQuery("SELECT * FROM ub.user WHERE id = ?1", User.class);
        q.setParameter(1, uid);
        List<User> res = q.getResultList();
        if(res == null || res.isEmpty()){
            return null;
        }
        
        User u = res.get(0);
        u.setCurActiveContext(getCurActive(uid));
        u.setExplicitInterests(getInterests(uid));
        u.setExplicitDislikes(getDisinterests(uid));
        u.setLikeList(getLikeVideos(uid));
        u.setDislikeList(getDislikeVideos(uid));
        u.setPreferences(getPreferences(uid));
        return u;
    }
    
    @Override
    public Context getCurActive(int uid) {
        Query q = em.createNativeQuery("SELECT * FROM ub.get_cur_active(?1)", Context.class);
        q.setParameter(1, uid);
        return (Context) q.getSingleResult();
    }
    

    @Override
    public List<Entity> getInterests(int uid) {
        Query q = em.createNativeQuery("SELECT * FROM ub.get_interests(?1)", Entity.class);
        q.setParameter(1, uid);
        return q.getResultList();
    }

    @Override
    public List<Entity> getDisinterests(int uid) {
        Query q = em.createNativeQuery("SELECT * FROM ub.get_disinterests(?1)", Entity.class);
        q.setParameter(1, uid);
        return q.getResultList();
    }

    @Override
    public List<Video> getLikeVideos(int uid) {
        Query q = em.createNativeQuery("SELECT * FROM ub.get_like_videos(?1)", Video.class);
        q.setParameter(1, uid);
        return q.getResultList();
    }

    @Override
    public List<Video> getDislikeVideos(int uid) {
        Query q = em.createNativeQuery("SELECT * FROM ub.get_dislike_videos(?1)", Video.class);
        q.setParameter(1, uid);
        return q.getResultList();
    }

    @Override
    public boolean isValid(String uname) {
        Query q = em.createNativeQuery("SELECT * FROM ub.user WHERE username = ?1", User.class);
        q.setParameter(1, uname);
        List<User> u = q.getResultList();
        return (u == null || u.isEmpty());
    }

    @Override
    public void setLike(int uid, int cid, int vid, boolean like) {
        Query q = em.createNativeQuery("INSERT INTO ub.user_videos (uid, ctx, vid, \"like\", \"timestamp\") VALUES (?1, ?2, ?3, ?4, ?5) returning \"timestamp\"");
        q.setParameter(1, uid);
        q.setParameter(2, cid);
        q.setParameter(3, vid);
        q.setParameter(4, like);
        Date d = Calendar.getInstance().getTime();
        q.setParameter(5, new Timestamp(d.getTime()));
        q.getResultList();
    }

    @Override
    public void setInterest(int uid, int cid, String eid, boolean like) {
        Query q = em.createNativeQuery("INSERT INTO ub.user_entities (uid, ctx, eid, is_cls, \"like\", \"timestamp\") VALUES (?1, ?2, ?3, ?4, ?5, ?6) returning \"timestamp\"");
        q.setParameter(1, uid);
        q.setParameter(2, cid);
        q.setParameter(3, Integer.parseInt(eid.replace("Class", "").replace("Instance", "")));
        q.setParameter(4, eid.startsWith("Class"));
        q.setParameter(5, like);
        Date d = Calendar.getInstance().getTime();
        q.setParameter(6, new Timestamp(d.getTime()));
        q.getResultList();
    }

    @Override
    public void updatePreference(int uid, boolean threshold, int v_threshold, int e_threshold, int nvid, int nint) {
        Query q = em.createNativeQuery("UPDATE ub.user_preferences SET use_threshold = ?1, video_threshold = ?2, interest_threshold = ?3,"
                + " n_video = ?4, n_interest = ?5 WHERE uid = ?6 RETURNING uid");
        q.setParameter(1, threshold);
        q.setParameter(2, v_threshold);
        q.setParameter(3, e_threshold);
        q.setParameter(4, nvid);
        q.setParameter(5, nint);
        q.setParameter(6, uid);
        q.getResultList();
    }

    @Override
    public void forgetUser(int uid) {
        Query q = em.createNativeQuery("SELECT count(*) FROM ub.forget_user(?1)");
        q.setParameter(1, uid);
        q.getSingleResult();
    }

    @Override
    public Preference getPreferences(int uid) {
        Query q = em.createNativeQuery("SELECT * FROM ub.user_preferences WHERE uid = ?1", Preference.class);
        q.setParameter(1, uid);
        return (Preference) q.getSingleResult();
    }

    @Override
    public void setActiveContext(int uid, int cid) {
        Query q = em.createNativeQuery("SELECT count(*) FROM ub.set_active_ctx(?1, ?2)");
        q.setParameter(1, cid);
        q.setParameter(2, uid);
        q.getSingleResult();
    }

    @Override
    public int addContext(int cid, String n) {
        Query q = em.createNativeQuery("INSERT INTO ub.context (name, parent) VALUES (?1, ?2) RETURNING id");
        q.setParameter(1, n);
        q.setParameter(2, cid);
        return (Integer) q.getSingleResult();
    }

    @Override
    public void renameContext(int cid, String n) {
        Query q = em.createNativeQuery("UPDATE ub.context SET name= ?1 WHERE id = ?2 RETURNING name");
        q.setParameter(1, n);
        q.setParameter(2, cid);
        q.getResultList();
    }

    @Override
    public List<Context> getContexts(int uid) {
        Query q = em.createNativeQuery("SELECT * FROM ub.get_all_contexts(?1)", Context.class);
        q.setParameter(1, uid);
        return q.getResultList();
    }
    
    public List<String> getAllUsers(int src) {
        Query q = em.createNativeQuery("SELECT * FROM ub.get_all_users(?1)");
        q.setParameter(1, src);
        return q.getResultList();
    }
    
    public List<Integer> getVideosOfUser(int src, String uid) {
        Query q = em.createNativeQuery("SELECT * FROM ub.get_all_favorites(?1, ?2)");
        q.setParameter(1, src);
        q.setParameter(2, uid);
        return q.getResultList();
    }

}
